home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfsrecov / files.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-17  |  51.3 KB  |  1,833 lines

  1. /* 
  2.  * file.c --
  3.  *
  4.  *    File and directory manipulation routines for the lfsrecov program.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that this copyright
  10.  * notice appears in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.5 91/02/09 13:24:44 ouster Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "lfslib.h"
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <sys/file.h>
  24. #include <option.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <alloca.h>
  28. #include <bstring.h>
  29. #include <unistd.h>
  30. #include <bit.h>
  31. #include <time.h>
  32. #include <sys/time.h>
  33. #include <assert.h>
  34. #include <hash.h>
  35. #include <libc.h>
  36.  
  37. #include "lfsrecov.h"
  38. #include "desc.h"
  39. #include "fileop.h"
  40. #include "usage.h"
  41. #include "dirlog.h"
  42.  
  43. LfsFile *FindLost_FoundDir _ARGS_((Lfs *lfsPtr));
  44.  
  45. void CheckVersionTruncNum _ARGS_((int startAddress, int fileNumber, 
  46.             int truncVersion, int numBlocks,
  47.             int numDataBlocks, int *blockArray));
  48.  
  49.  
  50. /*
  51.  *----------------------------------------------------------------------
  52.  *
  53.  * RecordBlockUsageChange --
  54.  *
  55.  *    Record in the SegUsage map any changes that we caused by a
  56.  *    new inode going out
  57.  *
  58.  * Results:
  59.  *    None.
  60.  *
  61.  * Side effects:
  62.  *    None.
  63.  *
  64.  *----------------------------------------------------------------------
  65.  */
  66.  
  67. void
  68. RecordBlockUsageChange(fileNumber, oldFilePtr, newFilePtr)
  69.     int    fileNumber;    /* File number being changed. */
  70.     LfsFile    *oldFilePtr; /* Old version of file, NIL if didn't exist. */
  71.     LfsFile    *newFilePtr; /* New version of file, NIL if deleted. */
  72. {
  73.     LfsFileDescriptor *oldDescPtr, *newDescPtr;    
  74.     int numBytes[2], numBlocks[2], lastByteBlock[2], lastByteBlockSize[2], i;
  75.     int oldBlock, newBlock;
  76.  
  77.     oldDescPtr = newDescPtr = (LfsFileDescriptor *) NIL;
  78.  
  79.     if (oldFilePtr != (LfsFile *) NIL) {
  80.     oldDescPtr = LfsFileFetchDesc(oldFilePtr);
  81.     if (oldDescPtr->common.lastByte == -1) {
  82.         oldFilePtr = (LfsFile *) NIL;
  83.     }
  84.     }
  85.     if (newFilePtr != (LfsFile *) NIL) {
  86.     newDescPtr = LfsFileFetchDesc(newFilePtr);
  87.     if (newDescPtr->common.lastByte == -1) {
  88.         newFilePtr = (LfsFile *) NIL;
  89.     }
  90.     }
  91.     if ((oldFilePtr == (LfsFile *) NIL) && (newFilePtr == (LfsFile *) NIL)) {
  92.     /*
  93.      * Nothing to do if file blocks didn't change.
  94.      */
  95.     return;
  96.     }
  97.  
  98.  
  99.     if (oldFilePtr == (LfsFile *) NIL) {
  100.     numBytes[0] = -1;
  101.     numBlocks[0] = -1;
  102.     lastByteBlock[0] = -1;
  103.     lastByteBlockSize[0] = -1;
  104.     } else {
  105.     numBytes[0] = (oldDescPtr->common.lastByte+1+blockSize-1)/blockSize;
  106.     numBytes[0] *= blockSize;
  107.     numBlocks[0] = (numBytes[0] + FS_BLOCK_SIZE - 1)/FS_BLOCK_SIZE;
  108.     lastByteBlock[0] = oldDescPtr->common.lastByte/FS_BLOCK_SIZE;
  109.     lastByteBlockSize[0] = numBytes[0] - lastByteBlock[0] * FS_BLOCK_SIZE;
  110.     }
  111.     if (newFilePtr == (LfsFile *) NIL) {
  112.     numBytes[1] = -1;
  113.     numBlocks[1] = -1;
  114.     lastByteBlock[1] = -1;
  115.     lastByteBlockSize[1] = -1;
  116.     } else {
  117.     numBytes[1] = (newDescPtr->common.lastByte+1+blockSize-1)/blockSize;
  118.     numBytes[1] *= blockSize;
  119.     numBlocks[1] = (numBytes[0] + FS_BLOCK_SIZE - 1)/FS_BLOCK_SIZE;
  120.     lastByteBlock[1] = newDescPtr->common.lastByte/FS_BLOCK_SIZE;
  121.     lastByteBlockSize[1] = numBytes[1] - lastByteBlock[1] * FS_BLOCK_SIZE;
  122.     }
  123.  
  124.  
  125.     /*
  126.      * Record any DBL_INDIRECT blocks first.
  127.      */
  128.     if ((numBlocks[0] >= (FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK)) ||
  129.         (numBlocks[1] >= (FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK))) {
  130.     oldBlock = (oldFilePtr != (LfsFile *) NIL) ? 
  131.             oldDescPtr->common.indirect[1] : FSDM_NIL_INDEX;
  132.     newBlock = (newFilePtr != (LfsFile *) NIL) ? 
  133.             newDescPtr->common.indirect[1] : FSDM_NIL_INDEX;
  134.     if (oldBlock != newBlock) { 
  135.         RecordIndirectBlockUsage(oldFilePtr, newFilePtr, -2,
  136.             FSDM_NUM_DIRECT_BLOCKS + FSDM_INDICES_PER_BLOCK,
  137.             FSDM_INDICES_PER_BLOCK, lastByteBlock, 
  138.             lastByteBlockSize);
  139.     }
  140.     } 
  141.     /*
  142.      * Followed by any INDIRECT blocks.
  143.      */
  144.     if ((numBlocks[0] >= FSDM_NUM_DIRECT_BLOCKS) ||
  145.         (numBlocks[1] >=(FSDM_NUM_DIRECT_BLOCKS))) {
  146.     oldBlock = (oldFilePtr != (LfsFile *) NIL) ? 
  147.             oldDescPtr->common.indirect[0] : FSDM_NIL_INDEX;
  148.     newBlock = (newFilePtr != (LfsFile *) NIL) ? 
  149.             newDescPtr->common.indirect[0] : FSDM_NIL_INDEX;
  150.     if (oldBlock != newBlock) { 
  151.         RecordIndirectBlockUsage(oldFilePtr, newFilePtr, -1,
  152.         FSDM_NUM_DIRECT_BLOCKS, 1, lastByteBlock, 
  153.         lastByteBlockSize);
  154.     }
  155.     }
  156.     /*
  157.      * Finally the DIRECT blocks.
  158.      */
  159.     for (i = 0; (i < FSDM_NUM_DIRECT_BLOCKS); i++) {
  160.     oldBlock = (oldFilePtr != (LfsFile *) NIL) ? 
  161.             oldDescPtr->common.direct[i] : FSDM_NIL_INDEX;
  162.     newBlock = (newFilePtr != (LfsFile *) NIL) ? 
  163.             newDescPtr->common.direct[i] : FSDM_NIL_INDEX;
  164.     if (oldBlock != newBlock) {
  165.         if (lastByteBlock[0] != i) {
  166.         LfsSegUsageAdjustBytes(lfsPtr,oldBlock, -FS_BLOCK_SIZE);
  167.         } else {
  168.         LfsSegUsageAdjustBytes(lfsPtr,oldBlock, -lastByteBlockSize[0]);
  169.         }
  170.         if (lastByteBlock[1] != i) {
  171.         LfsSegUsageAdjustBytes(lfsPtr,newBlock, FS_BLOCK_SIZE);
  172.         } else {
  173.         LfsSegUsageAdjustBytes(lfsPtr,newBlock, lastByteBlockSize[1]);
  174.         }
  175.     }
  176.     }
  177. }
  178.  
  179. /*
  180.  *----------------------------------------------------------------------
  181.  *
  182.  * RecordIndirectBlockUsage --
  183.  *
  184.  *    Record the usage of an file's indirect block.
  185.  *
  186.  * Results:
  187.  *    None.
  188.  *
  189.  * Side effects:
  190.  *    None.
  191.  *
  192.  *----------------------------------------------------------------------
  193.  */
  194. void
  195. RecordIndirectBlockUsage(oldFilePtr, newFilePtr, virtualBlockNum,
  196.     startBlockNum, step, lastByteBlock, lastByteBlockSize) 
  197.     LfsFile  *oldFilePtr;        /* old File being operatored on. */
  198.     LfsFile  *newFilePtr;        /* new File being operatored on. */
  199.     int      virtualBlockNum;    /* Virtual block number for this indirect 
  200.                  * block. */
  201.     int      startBlockNum;    /* Starting block number of this virtual
  202.                  * Block. */
  203.     int      step;            /* Number of blocks covered by each virtual
  204.                  * block entry. */
  205.     int      lastByteBlock[2];    /* Block containing last byte each  file. */
  206.     int      lastByteBlockSize[2];    /* Size of last block  of each file. */
  207. {
  208.     ReturnStatus status;
  209.     LfsFileBlock    *oldFileBlockPtr, *newFileBlockPtr;
  210.     int        *oldBlockPtrs, *newBlockPtrs, i, cstep, childBlockNum;
  211.     int        oldBlock, newBlock;
  212.  
  213.     newBlockPtrs = oldBlockPtrs = (int *) NIL;
  214.     if (oldFilePtr != (LfsFile *) NIL) { 
  215.     status = LfsFileBlockFetch(oldFilePtr, virtualBlockNum, &oldFileBlockPtr);
  216.     if (status == SUCCESS) {
  217.         oldBlockPtrs = (int *) LfsFileBlockMem(oldFileBlockPtr);
  218.     } 
  219.     }
  220.     if (newFilePtr != (LfsFile *) NIL) { 
  221.     status = LfsFileBlockFetch(newFilePtr, virtualBlockNum, &newFileBlockPtr);
  222.     if (status == SUCCESS) {
  223.         newBlockPtrs = (int *) LfsFileBlockMem(newFileBlockPtr);
  224.     }
  225.     } 
  226.     if (newBlockPtrs == oldBlockPtrs) {
  227.     return;
  228.     }
  229.     if (step != 1) {
  230.     cstep = step/FSDM_INDICES_PER_BLOCK;
  231.     childBlockNum = -((FSDM_NUM_INDIRECT_BLOCKS+1));
  232.     for (i = 0; i < FSDM_INDICES_PER_BLOCK; i++) { 
  233.         oldBlock = (oldBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  234.                             oldBlockPtrs[i];
  235.         newBlock = (newBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  236.                             newBlockPtrs[i];
  237.         if (oldBlock != newBlock) {
  238.             RecordIndirectBlockUsage(oldFilePtr, newFilePtr,
  239.                 childBlockNum, startBlockNum, cstep, 
  240.                 lastByteBlock, lastByteBlockSize);
  241.         }
  242.         startBlockNum += step;
  243.         childBlockNum--;
  244.     }
  245.     } else { 
  246.     for (i = 0; i < FSDM_INDICES_PER_BLOCK; i++) {
  247.         oldBlock = (oldBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  248.                             oldBlockPtrs[i];
  249.         newBlock = (newBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  250.                             newBlockPtrs[i];
  251.         if (startBlockNum + i == lastByteBlock[0]) {
  252.           LfsSegUsageAdjustBytes(lfsPtr,oldBlock, -lastByteBlockSize[0]);
  253.         } else  {
  254.           LfsSegUsageAdjustBytes(lfsPtr,oldBlock, -FS_BLOCK_SIZE);
  255.         }
  256.         if (startBlockNum + i == lastByteBlock[1]) {
  257.           LfsSegUsageAdjustBytes(lfsPtr,newBlock, lastByteBlockSize[1]);
  258.         } else  {
  259.           LfsSegUsageAdjustBytes(lfsPtr,newBlock, FS_BLOCK_SIZE);
  260.         }
  261.     }
  262.     }
  263.     oldBlock = (oldBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  264.                 LfsFileBlockAddress(oldFileBlockPtr);
  265.     newBlock = (newBlockPtrs == (int *) NIL) ? FSDM_NIL_INDEX : 
  266.                 LfsFileBlockAddress(newFileBlockPtr);
  267.     if (oldBlock != newBlock) {
  268.      LfsSegUsageAdjustBytes(lfsPtr,oldBlock, -FS_BLOCK_SIZE);
  269.      LfsSegUsageAdjustBytes(lfsPtr,newBlock, FS_BLOCK_SIZE);
  270.     } 
  271. }
  272.  
  273. /*
  274.  *----------------------------------------------------------------------
  275.  *
  276.  * AddEntryToDirectory --
  277.  *
  278.  *    Add a directory entry to the specified directory and offset. 
  279.  *    This routine is used to redo operations on directory
  280.  *    lost during a crash because the directory block didn't make
  281.  *    it out. An offset of -1 means add to any available place in
  282.  *     the directory.
  283.  *
  284.  * Results:
  285.  *    SUCCESS if operation completed. 
  286.  *
  287.  * Side effects:
  288.  *    A block of the directory may be modified.
  289.  *
  290.  *----------------------------------------------------------------------
  291.  */
  292.  
  293. ReturnStatus
  294. AddEntryToDirectory(dirFileNumber, dirOffset, dirEntryPtr, isDirectory,mayExist)
  295.     int    dirFileNumber;    /* Directory descriptor number. */
  296.     int    dirOffset;    /* Offset into directory of entry. */
  297.     Fslcl_DirEntry *dirEntryPtr; /* Directory entry to addr. */
  298.     Boolean    isDirectory;    /* TRUE if directory entry is for a 
  299.                  * subdirectory. */
  300.     Boolean    mayExist;     /* The directory entry may exist. */
  301. {
  302.     int    blockNum, offset, length,  blockOffset;
  303.     int    newRecordLen;
  304.     ReturnStatus    status;
  305.     LfsFileDescriptor    *descPtr;
  306.     Fslcl_DirEntry *newEntryPtr;
  307.     LfsFile    *dirFilePtr;
  308.     LfsFileBlock    *dirBlockPtr;
  309.     char    *blockPtr;
  310.  
  311.     stats.dirEntryAdded++;
  312.     if (verboseFlag) {
  313.     char buffer[FS_MAX_NAME_LENGTH+1];
  314.     bcopy(dirEntryPtr->fileName, buffer, dirEntryPtr->nameLength);
  315.     buffer[dirEntryPtr->nameLength] = 0;
  316.     printf("Adding file %d under name \"%s\" to directory %d\n",
  317.         dirEntryPtr->fileNumber, buffer, dirFileNumber);
  318.     }
  319.  
  320.     status = LfsFileOpen(lfsPtr, dirFileNumber, &dirFilePtr);
  321.     if (status != SUCCESS) {
  322.     return status;
  323.     }
  324.  
  325.  
  326.     descPtr = LfsFileFetchDesc(dirFilePtr);
  327.     if (descPtr->common.fileType != FS_DIRECTORY) {
  328.     panic("Trying to add entry to non-directory %d\n", dirFileNumber);
  329.     LfsFileClose(dirFilePtr);
  330.     return FAILURE;
  331.     }
  332.     length = descPtr->common.lastByte+1;
  333.     if ((length % FSLCL_DIR_BLOCK_SIZE) != 0) {
  334.     panic("Directory %d has bad length %d\n", dirFileNumber, length);
  335.     LfsFileClose(dirFilePtr);
  336.     return FAILURE;
  337.     }
  338.     if (dirOffset == -1) {
  339.     int    recordLength;
  340.     /*
  341.      * Find an available slot. 
  342.      */
  343.     dirOffset = 0;
  344.     recordLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  345.     for (blockNum = 0; !dirOffset; blockNum++) {
  346.         status = LfsFileBlockFetch(dirFilePtr, blockNum, &dirBlockPtr);
  347.         if (status != SUCCESS) {
  348.         dirOffset = blockNum * FS_BLOCK_SIZE;
  349.         break;
  350.         }
  351.         blockOffset = 0;
  352.         blockSize = LfsFileBlockSize(dirBlockPtr);
  353.         blockPtr = LfsFileBlockMem(dirBlockPtr);
  354.         while (blockOffset < blockSize) {
  355.         newEntryPtr = (Fslcl_DirEntry *) (blockPtr + blockOffset);
  356.         if (newEntryPtr->fileNumber != 0) {
  357.             int    extraBytes;
  358.             /*
  359.              * A valid directory record.
  360.              * Check the left-over bytes attached to this record.
  361.              */
  362.             extraBytes = newEntryPtr->recordLength -
  363.                  Fslcl_DirRecLength(newEntryPtr->nameLength);
  364.             if (extraBytes >= recordLength) {
  365.             /*
  366.              * Can fit new entry in the space left over.
  367.              */ 
  368.             dirOffset = blockNum * FS_BLOCK_SIZE + blockOffset +
  369.                 Fslcl_DirRecLength(newEntryPtr->nameLength);
  370.             break;
  371.             }
  372.         } else {
  373.             /*
  374.              * A deleted name in the directory.
  375.              */
  376.             if (newEntryPtr->recordLength >= recordLength) {
  377.             dirOffset = blockNum * FS_BLOCK_SIZE + blockOffset ;
  378.             break;
  379.             }
  380.         }
  381.         blockOffset += newEntryPtr->recordLength;
  382.        }
  383.        if (!dirOffset && (blockSize != FS_BLOCK_SIZE)) {
  384.         dirOffset = blockNum * FS_BLOCK_SIZE + blockSize;
  385.        }
  386.     }
  387.     }
  388.  
  389.  
  390.     if (dirOffset >= descPtr->common.lastByte) {
  391.     status = GrowDirectory(dirFilePtr, dirOffset);
  392.     if (status != SUCCESS) {
  393.         LfsFileClose(dirFilePtr);
  394.         return FAILURE;
  395.     }
  396.     }
  397.     blockNum = dirOffset/FS_BLOCK_SIZE;
  398.     status = LfsFileBlockFetch(dirFilePtr, blockNum, &dirBlockPtr);
  399.     if (status != SUCCESS) {
  400.     panic("Can't find block %d of directory %d\n", blockNum, dirFileNumber);
  401.     LfsFileClose(dirFilePtr);
  402.     return FAILURE;
  403.     }
  404.     blockPtr = LfsFileBlockMem(dirBlockPtr);
  405.     blockPtr += (dirOffset / FSLCL_DIR_BLOCK_SIZE) * FSLCL_DIR_BLOCK_SIZE - 
  406.         ((dirOffset / FS_BLOCK_SIZE) * FS_BLOCK_SIZE);
  407.     blockOffset = 0;
  408.     offset = dirOffset % FSLCL_DIR_BLOCK_SIZE;
  409.     newEntryPtr = (Fslcl_DirEntry *) NULL;
  410.     while (blockOffset < FSLCL_DIR_BLOCK_SIZE) {
  411.     if (blockOffset >= offset) {
  412.         break;
  413.     }
  414.     newEntryPtr = (Fslcl_DirEntry *) (blockPtr + blockOffset);
  415.     if (newEntryPtr->recordLength <= 0) {
  416.         panic("Corrupted directory %d\n", dirFileNumber);
  417.     }
  418.     blockOffset += newEntryPtr->recordLength;
  419.     }
  420.     if (blockOffset == offset) {
  421.     /*
  422.      * A directory entry ends at this offset. We make sure something
  423.      * is not already valid there and add it.
  424.      */
  425.     newEntryPtr = (Fslcl_DirEntry *) (blockPtr + offset);
  426.     if (newEntryPtr->fileNumber != 0) {
  427.         if (!mayExist) {
  428.             panic("Valid directory entry in %d at offset %d\n", 
  429.                 dirFileNumber, offset);
  430.         }
  431.         if ((newEntryPtr->fileNumber != dirEntryPtr->fileNumber) ||
  432.             (newEntryPtr->nameLength != dirEntryPtr->nameLength) ||
  433.             (strncmp(newEntryPtr->fileName, dirEntryPtr->fileName,
  434.                 dirEntryPtr->nameLength))) {
  435.             panic("Wrong directory entry in %d at offset %d\n",
  436.                 dirFileNumber, offset);
  437.         }
  438.         LfsFileClose(dirFilePtr);
  439.         return SUCCESS;
  440.     }
  441.     newRecordLen = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  442.     if (newRecordLen > newEntryPtr->recordLength) {
  443.         panic("Directory entry in %d at %d is too large\n",
  444.             dirFileNumber, offset);
  445.     }
  446.     newEntryPtr->fileNumber = dirEntryPtr->fileNumber;
  447.     newEntryPtr->nameLength = dirEntryPtr->nameLength;
  448.     bcopy(dirEntryPtr->fileName, newEntryPtr->fileName, 
  449.             dirEntryPtr->nameLength);
  450.     newEntryPtr->fileName[dirEntryPtr->nameLength] = 0;
  451.     } else {
  452.     /*
  453.      * We are inserting in the middle of a previous entry.  We must
  454.      * shortten it. 
  455.      */
  456.     newRecordLen =  newEntryPtr->recordLength - (blockOffset - offset);
  457.     if (newRecordLen < Fslcl_DirRecLength(newEntryPtr->nameLength)) {
  458.         panic("Insert pattern doesn't fit.\n");
  459.     }
  460.     newEntryPtr->recordLength = newRecordLen;
  461.     newEntryPtr = (Fslcl_DirEntry *) (blockPtr + offset);
  462.     newEntryPtr->fileNumber = dirEntryPtr->fileNumber;
  463.     newEntryPtr->recordLength = blockOffset - offset;
  464.     newEntryPtr->nameLength = dirEntryPtr->nameLength;
  465.     bcopy(dirEntryPtr->fileName, newEntryPtr->fileName, 
  466.             dirEntryPtr->nameLength);
  467.     newEntryPtr->fileName[dirEntryPtr->nameLength] = 0;
  468.     }
  469.     if (isDirectory) {
  470.     /*
  471.      * If we added a subdirectory we need to update the parent's link count
  472.      * to reflect the ".." entry pointing at it.
  473.      */
  474.     descPtr->common.numLinks++;
  475.     LfsFileStoreDesc(dirFilePtr);
  476.     }
  477.     status = LfsFileStoreBlock(dirBlockPtr, -1);
  478.     LfsFileClose(dirFilePtr);
  479.     return   status;
  480.  
  481. }
  482.  
  483. /*
  484.  *----------------------------------------------------------------------
  485.  *
  486.  * RemovedEntryFromDirectory --
  487.  *
  488.  *    Remote a directory entry from the specified directory and offset. 
  489.  *    This routine is used to redo operations on directory
  490.  *    lost during a crash because the directory block didn't make
  491.  *    it out. An offset -1 dirEntry may be anywhere in directory.
  492.  *
  493.  * Results:
  494.  *    SUCCESS if operation completed. 
  495.  *
  496.  * Side effects:
  497.  *    A block of the directory may be modified.
  498.  *
  499.  *----------------------------------------------------------------------
  500.  */
  501. ReturnStatus
  502. RemovedEntryFromDirectory(dirFileNumber, dirOffset, dirEntryPtr, 
  503.               isDirectory, mayBeGone)
  504.     int    dirFileNumber;    /* Directory descriptor number. */
  505.     int    dirOffset;    /* Offset into directory of entry. */
  506.     Fslcl_DirEntry *dirEntryPtr; /* Directory entry value. */
  507.     Boolean    isDirectory;    /* TRUE if rmdir. */
  508.     Boolean    mayBeGone;     /* The directory entry be already deleted. */
  509. {
  510.     int    blockNum, offset, length, blockOffset;
  511.     LfsFile    *dirFilePtr;
  512.     LfsFileBlock    *dirBlockPtr;
  513.     ReturnStatus    status;
  514.     LfsFileDescriptor    *descPtr;
  515.     Fslcl_DirEntry *lastDirEntryPtr, *newEntryPtr;
  516.     char    *blockPtr;
  517.  
  518.     stats.dirEntryRemoved++;
  519.     if (verboseFlag) {
  520.     char buffer[FS_MAX_NAME_LENGTH+1];
  521.     bcopy(dirEntryPtr->fileName, buffer, dirEntryPtr->nameLength);
  522.     buffer[dirEntryPtr->nameLength] = 0;
  523.     printf("Removing file %d under name \"%s\" from directory %d\n",
  524.         dirEntryPtr->fileNumber, buffer, dirFileNumber);
  525.     }
  526.  
  527.     blockNum = dirOffset/FS_BLOCK_SIZE;
  528.     status = LfsFileOpen(lfsPtr, dirFileNumber, &dirFilePtr);
  529.     if (status != SUCCESS) {
  530.     return status;
  531.     }
  532.     descPtr = LfsFileFetchDesc(dirFilePtr);
  533.     if (descPtr->common.fileType != FS_DIRECTORY) {
  534.     panic("Trying to delete entry from non-directory %d\n", dirFileNumber);
  535.     LfsFileClose(dirFilePtr);
  536.     return FAILURE;
  537.     }
  538.     length = descPtr->common.lastByte+1;
  539.     if ((length % FSLCL_DIR_BLOCK_SIZE) != 0) {
  540.     panic("Directory %d has bad length %d\n", dirFileNumber, length);
  541.     LfsFileClose(dirFilePtr);
  542.     return FAILURE;
  543.     }
  544.     if (dirOffset == -1) {
  545.     /*
  546.      * Find an available slot. 
  547.      */
  548.     dirOffset = 0;
  549.     for (blockNum = 0; !dirOffset; blockNum++) {
  550.         status = LfsFileBlockFetch(dirFilePtr, blockNum, &dirBlockPtr);
  551.         if (status != SUCCESS) {
  552.         dirOffset = blockNum * FS_BLOCK_SIZE;
  553.         break;
  554.         }
  555.         blockOffset = 0;
  556.         blockSize = LfsFileBlockSize(dirBlockPtr);
  557.         blockPtr = LfsFileBlockMem(dirBlockPtr);
  558.         while (blockOffset < blockSize) {
  559.         newEntryPtr = (Fslcl_DirEntry *) (blockPtr + blockOffset);
  560.         if (newEntryPtr->fileNumber == dirEntryPtr->fileNumber) {
  561.             dirOffset = blockNum * FS_BLOCK_SIZE + blockOffset;
  562.             break;
  563.         } 
  564.         blockOffset += newEntryPtr->recordLength;
  565.        }
  566.        if (blockSize != FS_BLOCK_SIZE) {
  567.            break;
  568.        }
  569.     }
  570.     if (dirOffset == 0) {
  571.         return FAILURE;
  572.     }
  573.     }
  574.  
  575.     if (dirOffset >= descPtr->common.lastByte) {
  576.     panic("Delete entry from directory %d at nonexistant offset %d\n",
  577.         dirFileNumber, blockNum);
  578.     }
  579.     status = LfsFileBlockFetch(dirFilePtr, blockNum, &dirBlockPtr);
  580.     if (status != SUCCESS) {
  581.     panic("Can't find block %d of directory %d\n", blockNum, dirFileNumber);
  582.     LfsFileClose(dirFilePtr);
  583.     return FAILURE;
  584.     }
  585.     blockPtr = LfsFileBlockMem(dirBlockPtr);
  586.     offset = dirOffset % FSLCL_DIR_BLOCK_SIZE;
  587.     blockPtr += (dirOffset / FSLCL_DIR_BLOCK_SIZE) * FSLCL_DIR_BLOCK_SIZE - 
  588.         ((dirOffset / FS_BLOCK_SIZE) * FS_BLOCK_SIZE);
  589.     blockOffset = 0;
  590.     lastDirEntryPtr = (Fslcl_DirEntry *) NULL;
  591.     while (blockOffset < FSLCL_DIR_BLOCK_SIZE) {
  592.     if (blockOffset >= offset) {
  593.         break;
  594.     }
  595.     lastDirEntryPtr = (Fslcl_DirEntry *) (blockPtr + blockOffset);
  596.     if (lastDirEntryPtr->recordLength <= 0) {
  597.         panic("Corrupted directory %d\n", dirFileNumber);
  598.     }
  599.     blockOffset += lastDirEntryPtr->recordLength;
  600.     }
  601.     if (blockOffset == offset) {
  602.     /*
  603.      * Make sure the entry is the correct one. We make sure something
  604.      * is not already valid there and add it.
  605.      */
  606.     newEntryPtr = (Fslcl_DirEntry *) (blockPtr + offset);
  607.     if ((newEntryPtr->fileNumber != dirEntryPtr->fileNumber) ||
  608.         (newEntryPtr->nameLength != dirEntryPtr->nameLength) ||
  609.         (strncmp(newEntryPtr->fileName, dirEntryPtr->fileName,
  610.             dirEntryPtr->nameLength))) {
  611.         if (!mayBeGone) {
  612.         panic("Wrong directory entry in %d at offset %d\n",
  613.             dirFileNumber, offset);
  614.         }
  615.         return SUCCESS;
  616.     }
  617.     newEntryPtr->fileNumber = 0;
  618.     if (lastDirEntryPtr != (Fslcl_DirEntry *)NULL) {
  619.         /*
  620.          * Grow the previous record so that it now includes
  621.          * this one.
  622.          */
  623.         lastDirEntryPtr->recordLength += newEntryPtr->recordLength;
  624.     }
  625.     if (isDirectory) {
  626.         descPtr->common.numLinks--;
  627.         LfsFileStoreDesc(dirFilePtr);
  628.     }
  629.     } else {
  630.     /*
  631.      * We are deleting in the middle of an entry.  
  632.      */
  633.     if (!mayBeGone) {
  634.         panic("Can find directory entry in %d at %d to delete.\n",
  635.             dirFileNumber, offset);
  636.     }
  637.     }
  638.     status = LfsFileStoreBlock(dirBlockPtr, -1);
  639.     LfsFileClose(dirFilePtr);
  640.     return status;
  641.  
  642. }
  643.  
  644.  
  645. /*
  646.  *----------------------------------------------------------------------
  647.  *
  648.  * GrowDirectory --
  649.  *
  650.  *    Add a block to a directory so that an entry at the specified 
  651.  *    offset can be created. The routine is used to add create room
  652.  *    to add entries to a directory after a crash.
  653.  *
  654.  * Results:
  655.  *    SUCCESS if operation completed. 
  656.  *
  657.  * Side effects:
  658.  *    A block of the directory will be created.
  659.  *
  660.  *----------------------------------------------------------------------
  661.  */
  662.  
  663.  
  664. ReturnStatus
  665. GrowDirectory(dirFilePtr, dirOffset)
  666.     LfsFile *dirFilePtr;    /* Open directory to grow. */
  667.     int     dirOffset;    /* Offset of entry we would like to include. */
  668. {
  669.     LfsFileDescriptor    *descPtr;
  670.     int            curBlockLength, neededBlockLength, blocksize;
  671.     Fslcl_DirEntry    *newDirEntryPtr;
  672.     LfsFileBlock        *dirBlockPtr;
  673.     char        *blockPtr;
  674.     ReturnStatus    status;
  675.  
  676.     descPtr = LfsFileFetchDesc(dirFilePtr);
  677.     curBlockLength = (descPtr->common.lastByte + 1 + (FSLCL_DIR_BLOCK_SIZE-1)) /
  678.                 FSLCL_DIR_BLOCK_SIZE;
  679.     neededBlockLength = (dirOffset + (FSLCL_DIR_BLOCK_SIZE-1)) / 
  680.                 FSLCL_DIR_BLOCK_SIZE;
  681.     if (neededBlockLength - curBlockLength > 1) {
  682.     /*
  683.      * One at most one block at a time. 
  684.      */
  685.     panic("Directory offset more that one block past current lastbyte\n");
  686.     }
  687.  
  688.     /*
  689.      * DB_PER_FSB - Directory blocks per file system blocks
  690.      */
  691. #define    DB_PER_FSB     (FS_BLOCK_SIZE/FSLCL_DIR_BLOCK_SIZE)
  692.  
  693.     if (neededBlockLength/DB_PER_FSB == curBlockLength/DB_PER_FSB) {
  694.     /*
  695.      * Just growing the existing block.
  696.      */
  697.     status = LfsFileBlockFetch(dirFilePtr, neededBlockLength/DB_PER_FSB,
  698.                 &dirBlockPtr);
  699.     if (status != SUCCESS) {
  700.         panic("Can't find block %d of directory %d\n", 
  701.             neededBlockLength/DB_PER_FSB, descPtr->fileNumber);
  702.     }
  703.     blockPtr = LfsFileBlockMem(dirBlockPtr);
  704.     blocksize = LfsFileBlockSize(dirBlockPtr);
  705.     newDirEntryPtr = (Fslcl_DirEntry *) (blockPtr + blocksize);
  706.     blocksize += FSLCL_DIR_BLOCK_SIZE;
  707.     } else {
  708.     /*
  709.      * Need to add a new block to the file.
  710.      */
  711.     blocksize = FSLCL_DIR_BLOCK_SIZE;
  712.     status = LfsFileBlockAlloc(dirFilePtr,neededBlockLength/DB_PER_FSB,
  713.                 FSLCL_DIR_BLOCK_SIZE, &dirBlockPtr);
  714.     blockPtr = LfsFileBlockMem(dirBlockPtr);
  715.     newDirEntryPtr = (Fslcl_DirEntry *) blockPtr;
  716.     }
  717.     descPtr->common.lastByte += FSLCL_DIR_BLOCK_SIZE;
  718.     bzero((char *) newDirEntryPtr, FSLCL_DIR_BLOCK_SIZE);
  719.     newDirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  720.     LfsFileStoreDesc(dirFilePtr);
  721.     return LfsFileStoreBlock(dirBlockPtr, blocksize);
  722. #undef DB_PER_FSB
  723. }
  724.  
  725.  
  726. /*
  727.  *----------------------------------------------------------------------
  728.  *
  729.  * FileTypeToString --
  730.  *
  731.  *    Covert a inode file type into a printable string.
  732.  *
  733.  * Results:
  734.  *    A printable string.
  735.  *
  736.  * Side effects:
  737.  *    None.
  738.  *
  739.  *----------------------------------------------------------------------
  740.  */
  741.  
  742.  
  743. char *
  744. FileTypeToString(fileType)
  745.     int fileType;
  746. {
  747.     static char *names[] = { "File", "Dir", "Symlink", "Rmtlink", "Dev", 
  748.                  "Rmtdev", "Pipe", "NamedPipe", "Pdev", "Pfs",
  749.                  "XtraFile", "Unknown"};
  750.  
  751.     if ((fileType < 0) || (fileType >= sizeof(names)/sizeof(names[0]))) {
  752.     fileType = sizeof(names)/sizeof(names[0])-1;
  753.     }
  754.     return names[fileType];
  755. }
  756.  
  757.  
  758.  
  759. /*
  760.  *----------------------------------------------------------------------
  761.  *
  762.  * UpdateDescLinkCount --
  763.  *
  764.  *    Update descriptor link count on a descriptor.
  765.  *
  766.  * Results:
  767.  *    None.
  768.  *
  769.  * Side effects:
  770.  *    None.
  771.  *
  772.  *----------------------------------------------------------------------
  773.  */
  774.  
  775. ReturnStatus
  776. UpdateDescLinkCount(opType, fileNumber, linkCount)
  777.     enum DescOpType opType;    /* OP_ABS or OP_REL. */
  778.     int           fileNumber; /* Directory entry being affected. */
  779.     int        linkCount;    /* New link count value or change. */
  780. {
  781.     LfsFile    *filePtr;
  782.     LfsFileDescriptor    *descPtr;
  783.     ReturnStatus status;
  784.  
  785.  
  786.     status = LfsFileOpen(lfsPtr, fileNumber, &filePtr);
  787.     if (status != SUCCESS) {
  788.     return status;
  789.     }
  790.     descPtr = LfsFileFetchDesc(filePtr);
  791.     if (opType == OP_ABS) {
  792.     descPtr->common.numLinks = linkCount;
  793.     } else if (opType == OP_REL) {
  794.     descPtr->common.numLinks += linkCount;
  795.     } else {
  796.     panic("Unknown op type in UpdateDescLinkCount\n");
  797.     }
  798.     status = LfsFileStoreDesc(filePtr);
  799.     LfsFileClose(filePtr);
  800.     return status;
  801. }
  802.  
  803. typedef struct LostFile {
  804.     List_Links    links;    /* Link pointers for list. MUST BE FIRST. */
  805.     int    dirFileNumber; /* Directory this file was to be created in. */
  806.     int    fileNumber;    /* File number being created. */
  807.     char fileName[FS_MAX_NAME_LENGTH+1];  
  808.             /* File name length. */
  809. } LostFile;
  810.  
  811. #define    ALLOC_SIZE(nameLength)    \
  812.     (sizeof(LostFile)-(FS_MAX_NAME_LENGTH+1)+(nameLength)+1)
  813.  
  814. static Boolean lostFileListInit = FALSE;
  815.  
  816. List_Links lostFileListHdr;
  817. List_Links addToLost_FoundListHdr;
  818. #define    lostFileList    (&lostFileListHdr)
  819. #define    addToLost_FoundList    (&addToLost_FoundListHdr)
  820.  
  821. /*
  822.  *----------------------------------------------------------------------
  823.  *
  824.  * RecordLostCreate --
  825.  *
  826.  *    Record the loss on a create operation so we have the <name, inode>
  827.  *    pairing for building up the lost+found directory.
  828.  *
  829.  * Results:
  830.  *    None.
  831.  *
  832.  * Side effects:
  833.  *    None.
  834.  *
  835.  *----------------------------------------------------------------------
  836.  */
  837.  
  838. void
  839. RecordLostCreate(dirFileNumber,dirEntryPtr)
  840.     int    dirFileNumber;    /* Directory of create. */
  841.     Fslcl_DirEntry    *dirEntryPtr; /* Entry lost. */
  842. {
  843.     int    fileNumber = dirEntryPtr->fileNumber;
  844.     LostFile    *lostFilePtr;
  845.  
  846.     if (!lostFileListInit) {
  847.     List_Init(lostFileList);
  848.     List_Init(addToLost_FoundList);
  849.     lostFileListInit = TRUE;
  850.     }
  851.     lostFilePtr = (LostFile *) malloc(ALLOC_SIZE(dirEntryPtr->nameLength));
  852.     List_InitElement((List_Links *) lostFilePtr);
  853.     lostFilePtr->dirFileNumber = dirFileNumber;
  854.     lostFilePtr->fileNumber = fileNumber;
  855.     bcopy(dirEntryPtr->fileName,lostFilePtr->fileName, dirEntryPtr->nameLength);
  856.     lostFilePtr->fileName[dirEntryPtr->nameLength] = '\000';
  857.  
  858.     List_Insert((List_Links *) lostFilePtr, LIST_ATREAR(lostFileList));
  859.  
  860. #ifdef notdef
  861.     if (verboseFlag) {
  862.     printf("Lost create in directory %d of file \"%s\" inode %d\n",
  863.             dirFileNumber, lostFilePtr->fileName, fileNumber);
  864.     }
  865. #endif
  866. }
  867.  
  868.  
  869. /*
  870.  *----------------------------------------------------------------------
  871.  *
  872.  * CreateLostDirectory --
  873.  *
  874.  *    Create a directory that was lost so that any files created
  875.  *    will be recoverable.
  876.  *
  877.  * Results:
  878.  *    SUCCESS if directory was created.
  879.  *
  880.  * Side effects:
  881.  *    None.
  882.  *
  883.  *----------------------------------------------------------------------
  884.  */
  885.  
  886. ReturnStatus
  887. CreateLostDirectory(fileNumber) 
  888.     int    fileNumber;    /* File number of directory. */
  889. {
  890.     LostFile    *lostFilePtr;
  891.     Boolean    foundIt = FALSE;
  892.     ReturnStatus status;
  893.  
  894.     if (!lostFileListInit) {
  895.     List_Init(lostFileList);
  896.     List_Init(addToLost_FoundList);
  897.     lostFileListInit = TRUE;
  898.     }
  899.     /*
  900.      * Check to see if file is in our list of lost creats.
  901.      */
  902.     for (lostFilePtr = (LostFile *) List_Last(lostFileList); 
  903.              !List_IsAtEnd(lostFileList,(List_Links *) lostFilePtr); 
  904.              lostFilePtr = (LostFile *)List_Prev((List_Links *) lostFilePtr)) {
  905.     if (lostFilePtr->fileNumber == fileNumber) {
  906.         foundIt = TRUE;
  907.         break;
  908.     }
  909.     }
  910.     if (verboseFlag) {
  911.     printf("Creating lost directory %d\n", fileNumber);
  912.     }
  913.  
  914.     status = MakeEmptyDirectory(fileNumber, -1);
  915.     if (status != SUCCESS) {
  916.     return status;
  917.     }
  918.     if (!foundIt) {
  919.         lostFilePtr = (LostFile *) malloc(ALLOC_SIZE(8));
  920.     List_InitElement((List_Links *) lostFilePtr);
  921.     lostFilePtr->dirFileNumber = fileNumber;
  922.     sprintf(lostFilePtr->fileName, "%d", fileNumber);
  923.     List_Insert((List_Links *) lostFilePtr, LIST_ATREAR(lostFileList));
  924.     }
  925.     List_Move((List_Links *)lostFilePtr, LIST_ATREAR(addToLost_FoundList));
  926.  
  927.     return status;
  928. }
  929.  
  930.  
  931.  
  932. /*
  933.  *----------------------------------------------------------------------
  934.  *
  935.  * SetParentDirectory --
  936.  *
  937.  *    Update a directory to reside in the specified directory fileNumber; 
  938.  *
  939.  * Results:
  940.  *    SUCCESS if update worked.
  941.  *
  942.  * Side effects:
  943.  *    None.
  944.  *
  945.  *----------------------------------------------------------------------
  946.  */
  947.  
  948. ReturnStatus
  949. SetParentDirectory(dirFileNumber, parentFileNumber) 
  950.     int    dirFileNumber;    /* File number of directory. */
  951.     int    parentFileNumber;    /* Parent file number. */
  952. {
  953.     ReturnStatus status;
  954.     LfsFile    *dirFilePtr;
  955.     LfsFileBlock *dirBlockPtr;
  956.     char    *dirBlock;
  957.     Fslcl_DirEntry *dirEntryPtr;
  958.  
  959.     status = LfsFileOpen(lfsPtr, dirFileNumber, &dirFilePtr);
  960.     if (status != SUCCESS) {
  961.     return status;
  962.     }
  963.     status = LfsFileBlockFetch(dirFilePtr, 0, &dirBlockPtr);
  964.     if (status != SUCCESS) {
  965.     return status;
  966.     }
  967.     dirBlock = LfsFileBlockMem(dirBlockPtr);
  968.     dirEntryPtr = (Fslcl_DirEntry *)dirBlock;
  969.     dirEntryPtr = (Fslcl_DirEntry *) (dirBlock + dirEntryPtr->recordLength);
  970.     if ((dirEntryPtr->nameLength != 2) ||
  971.     (dirEntryPtr->fileName[0] != '.') || 
  972.     (dirEntryPtr->fileName[1] != '.')) {
  973.     panic("Corrupted directory %d\n", dirFileNumber);
  974.     }
  975.     dirEntryPtr->fileNumber = parentFileNumber;
  976.     LfsFileStoreBlock(dirBlockPtr, -1);
  977.     LfsFileClose(dirFilePtr);
  978.  
  979.     return status;
  980. }
  981.  
  982.  
  983. /*
  984.  *----------------------------------------------------------------------
  985.  *
  986.  * MakeEmptyDirectory --
  987.  *
  988.  *    Initialize an empty directory.
  989.  *
  990.  * Results:
  991.  *    SUCCESS if operation worked.
  992.  *
  993.  * Side effects:
  994.  *    None.
  995.  *
  996.  *----------------------------------------------------------------------
  997.  */
  998.  
  999. ReturnStatus
  1000. MakeEmptyDirectory(fileNumber, parentFileNumber)
  1001.     int    fileNumber;    /* File number of directory. */
  1002.     int    parentFileNumber;    /* File number of parent. */
  1003. {
  1004.     LfsDescMapEntry *descMapEntryPtr;
  1005.     LfsFileDescriptor *descPtr;
  1006.     Fsdm_FileDescriptor    *fileDescPtr;
  1007.     LfsFile    *dirFilePtr;
  1008.     LfsFileBlock *dirBlockPtr;
  1009.     Fslcl_DirEntry *dirEntryPtr;
  1010.     char        *dirBlock;
  1011.     int        index;
  1012.     ReturnStatus    status;
  1013.  
  1014.     descPtr = (LfsFileDescriptor *)malloc(sizeof(LfsFileDescriptor));
  1015.  
  1016.     fileDescPtr = &descPtr->common;
  1017.     fileDescPtr->magic = FSDM_FD_MAGIC;
  1018.     fileDescPtr->flags = FSDM_FD_ALLOC|FSDM_FD_DIRTY;
  1019.     fileDescPtr->fileType = FS_DIRECTORY;
  1020.     fileDescPtr->permissions = 0755;
  1021.     fileDescPtr->uid = 0;
  1022.     fileDescPtr->gid = 0;
  1023.     fileDescPtr->lastByte = FSLCL_DIR_BLOCK_SIZE-1;
  1024.     fileDescPtr->lastByteXtra = 0;
  1025.     fileDescPtr->firstByte = -1;
  1026.     fileDescPtr->userType = FS_USER_TYPE_UNDEFINED;
  1027.     fileDescPtr->numLinks = 1;
  1028.  
  1029.     /*
  1030.      * Clear out device info.  It is set up properly by the make-device routine.
  1031.      */
  1032.     fileDescPtr->devServerID = -1;
  1033.     fileDescPtr->devType = -1;
  1034.     fileDescPtr->devUnit = -1;
  1035.  
  1036.     /*
  1037.      * Set the time stamps.  These times should come from the client.
  1038.      */
  1039.     fileDescPtr->createTime = time(0);
  1040.     fileDescPtr->accessTime = fileDescPtr->createTime;
  1041.     fileDescPtr->descModifyTime = fileDescPtr->createTime;
  1042.     fileDescPtr->dataModifyTime = fileDescPtr->createTime;
  1043.  
  1044.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1045.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  1046.     }
  1047.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1048.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  1049.     }
  1050.     fileDescPtr->numKbytes = 0;
  1051.     fileDescPtr->version = LfsGetCurrentTimestamp(lfsPtr);
  1052.  
  1053.     descPtr->fileNumber = fileNumber;
  1054.  
  1055.     status = LfsFileOpenDesc(lfsPtr, descPtr, &dirFilePtr);
  1056.     if (status == SUCCESS) {
  1057.     status = LfsFileBlockAlloc(dirFilePtr, 0, FSLCL_DIR_BLOCK_SIZE, 
  1058.                 &dirBlockPtr);
  1059.     }
  1060.     if (status != SUCCESS) {
  1061.     free((char *) descPtr);
  1062.     return status;
  1063.     }
  1064.     dirBlock = LfsFileBlockMem(dirBlockPtr);
  1065.     dirEntryPtr = (Fslcl_DirEntry *)dirBlock;
  1066.     dirEntryPtr->fileNumber = fileNumber;
  1067.     dirEntryPtr->nameLength = strlen(".");
  1068.     dirEntryPtr->recordLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  1069.     (void)strcpy(dirEntryPtr->fileName, ".");
  1070.     dirEntryPtr = (Fslcl_DirEntry *)((int)dirEntryPtr + dirEntryPtr->recordLength);
  1071.     dirEntryPtr->fileNumber = parentFileNumber;
  1072.     dirEntryPtr->nameLength = strlen("..");
  1073.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - Fslcl_DirRecLength(1);
  1074.     (void)strcpy(dirEntryPtr->fileName, "..");
  1075.  
  1076.     LfsFileStoreDesc(dirFilePtr);
  1077.     LfsFileStoreBlock(dirBlockPtr, -1);
  1078.     LfsFileClose(dirFilePtr);
  1079.  
  1080.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  1081.     if (!(descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  1082.     lfsPtr->descMap.checkPoint.numAllocDesc++;
  1083.     }
  1084.     descMapEntryPtr->flags = LFS_DESC_MAP_ALLOCED;
  1085.     descMapEntryPtr->truncVersion++;
  1086.     descMapEntryPtr->blockAddress = FSDM_NIL_INDEX;
  1087.     return SUCCESS;
  1088. }
  1089.  
  1090. /*
  1091.  *----------------------------------------------------------------------
  1092.  *
  1093.  * UpdateLost_Found --
  1094.  *
  1095.  *    Create and upate the lost and Found directory.
  1096.  *
  1097.  * Results:
  1098.  *    None.
  1099.  *
  1100.  * Side effects:
  1101.  *    None.
  1102.  *
  1103.  *----------------------------------------------------------------------
  1104.  */
  1105.  
  1106.  
  1107. void
  1108. UpdateLost_Found(lfsPtr) 
  1109.     Lfs    *lfsPtr;
  1110. {
  1111.     LfsFile    *dirFilePtr, *filePtr;
  1112.     ReturnStatus    status;
  1113.     ClientData    clientData;
  1114.     LostFile    *lostFilePtr;
  1115.     char    nameBuffer[FS_MAX_NAME_LENGTH+1];
  1116.     int        version, fileNumber, dirOffset;
  1117.  
  1118.     if (!lostFileListInit) {
  1119.     List_Init(lostFileList);
  1120.     List_Init(addToLost_FoundList);
  1121.     lostFileListInit = TRUE;
  1122.     }
  1123.     dirFilePtr = FindLost_FoundDir(lfsPtr);
  1124.  
  1125.     LIST_FORALL (addToLost_FoundList, (List_Links *) lostFilePtr) {
  1126.  
  1127.     stats.filesToLostFound++;
  1128.     sprintf(nameBuffer, "%s.%d", lostFilePtr->fileName, 
  1129.                     lostFilePtr->fileNumber);
  1130.     version = 1;
  1131.     do {
  1132.         status = LfsFileNameLookup(dirFilePtr, nameBuffer,
  1133.                 &fileNumber,&dirOffset);
  1134.         if (status == SUCCESS) {
  1135.         sprintf(nameBuffer, "%s.%d.%d", lostFilePtr->fileName, 
  1136.                     lostFilePtr->fileNumber, version);
  1137.         version++;
  1138.         }
  1139.     } while (status == SUCCESS);
  1140.     status = LfsFileOpen(lfsPtr, lostFilePtr->fileNumber, &filePtr);
  1141.     if (status != SUCCESS) {
  1142.         panic("Can't open created lost directory.\n");
  1143.     }
  1144.     status = LfsFileAddToDirectory(dirFilePtr, filePtr, nameBuffer);
  1145.     if (status != SUCCESS) {
  1146.         panic("Can't add name to lost+found directory.\n");
  1147.     }
  1148.     LfsFileClose(filePtr);
  1149.     }
  1150.  
  1151.      clientData = (ClientData) NIL;
  1152.      while (ScanUnrefDesc(&clientData, &fileNumber)) {
  1153.      status = LfsFileOpen(lfsPtr, fileNumber, &filePtr);
  1154.      if (status == FS_FILE_NOT_FOUND) {
  1155.         /*
  1156.          * File has been deleted. Skip it.
  1157.          */
  1158.         continue;
  1159.      }
  1160.      if (status != SUCCESS) {
  1161.         panic("Can't open unreferenced file.\n");
  1162.      }
  1163.      sprintf(nameBuffer, "unref.%d", fileNumber);
  1164.      version = 1;
  1165.      do {
  1166.         status = LfsFileNameLookup(dirFilePtr, nameBuffer,
  1167.                 &fileNumber,&dirOffset);
  1168.         if (status == SUCCESS) {
  1169.         sprintf(nameBuffer, "unref,%d.%d", fileNumber, version); 
  1170.         version++;
  1171.         }
  1172.     } while (status == SUCCESS);
  1173.      status = LfsFileAddToDirectory(dirFilePtr, filePtr, nameBuffer);
  1174.      if (status != SUCCESS) {
  1175.          panic("Can't add name to lost+found directory.\n");
  1176.      }
  1177.      LfsFileClose(filePtr);
  1178.     }
  1179.     ScanUnrefDescEnd(&clientData);
  1180.     LfsFileClose(dirFilePtr);
  1181. }
  1182.  
  1183.  
  1184. /*
  1185.  *----------------------------------------------------------------------
  1186.  *
  1187.  * LfsFileAddToDirectory --
  1188.  *
  1189.  *    Add the specified file to the specified directory under the
  1190.  *    specified name.
  1191.  *
  1192.  * Results:
  1193.  *    SUCCESS if everything worked.
  1194.  *
  1195.  * Side effects:
  1196.  *    None.
  1197.  *
  1198.  *----------------------------------------------------------------------
  1199.  */
  1200.  
  1201. ReturnStatus 
  1202. LfsFileAddToDirectory(dirFilePtr, filePtr, name)
  1203.     LfsFile *dirFilePtr;
  1204.     LfsFile *filePtr;
  1205.     char *name;
  1206. {
  1207.     Fslcl_DirEntry    dirEntry;
  1208.     LfsFileDescriptor    *descPtr, *dirDescPtr;
  1209.     ReturnStatus    status;
  1210.  
  1211.  
  1212.     dirDescPtr = LfsFileFetchDesc(dirFilePtr);
  1213.     descPtr = LfsFileFetchDesc(filePtr);
  1214.  
  1215.     dirEntry.fileNumber = descPtr->fileNumber;
  1216.     dirEntry.nameLength = strlen(name);
  1217.     strcpy(dirEntry.fileName, name);
  1218.     dirEntry.recordLength = Fslcl_DirRecLength(dirEntry.nameLength);
  1219.  
  1220.     status = AddEntryToDirectory(dirDescPtr->fileNumber, -1, &dirEntry, 
  1221.             (descPtr->common.fileType == FS_DIRECTORY), FALSE);
  1222.     if (status != SUCCESS) {
  1223.     panic("Can't add file to directory.\n");
  1224.     }
  1225.     descPtr->common.numLinks++;
  1226.     LfsFileStoreDesc(filePtr);
  1227.     if (descPtr->common.fileType == FS_DIRECTORY) {
  1228.     SetParentDirectory(descPtr->fileNumber, dirDescPtr->fileNumber);
  1229.     }
  1230.     return status;
  1231. }
  1232.  
  1233. LfsFile *
  1234. FindLost_FoundDir(lfsPtr)
  1235.     Lfs    *lfsPtr;
  1236. {
  1237.     LfsFile    *rootFilePtr, *dirFilePtr;
  1238.     int    fileNumber;
  1239.     ReturnStatus    status;
  1240.     int            dirOffset;
  1241.  
  1242.     status = LfsFileOpen(lfsPtr, FSDM_ROOT_FILE_NUMBER, &rootFilePtr);
  1243.     if (status != SUCCESS) {
  1244.     panic("Can't open root file system.\n");
  1245.     }
  1246.     status = LfsFileNameLookup(rootFilePtr, "lost+found", &fileNumber,
  1247.             &dirOffset);
  1248.     if (status != SUCCESS) {
  1249.     if (status == FS_FILE_NOT_FOUND) {
  1250.         status = LfsGetNewFileNumber(lfsPtr, FSDM_ROOT_FILE_NUMBER,
  1251.                 &fileNumber);
  1252.         if (status != SUCCESS) {
  1253.         panic("Can't allocated file number for lost+found directory\n");
  1254.         }
  1255.         status = MakeEmptyDirectory(fileNumber, FSDM_ROOT_FILE_NUMBER);
  1256.         if (verboseFlag) {
  1257.         printf("Can't find lost+found dir - creating at %d\n", fileNumber);
  1258.         }
  1259.         if (status != SUCCESS) {
  1260.         panic("Can't make new lost+found directory\n");
  1261.         }
  1262.     } else {
  1263.         panic("Can't open lost+found directory\n");
  1264.     }
  1265.     status = LfsFileOpen(lfsPtr, fileNumber, &dirFilePtr);
  1266.     if (status != SUCCESS) {
  1267.         panic("Can't open lost+found directory");
  1268.     }
  1269.     status = LfsFileAddToDirectory(rootFilePtr, dirFilePtr, "lost+found");
  1270.     if (status != SUCCESS) {
  1271.         panic("Can't add file to directory");
  1272.     }
  1273.     } else {
  1274.     status = LfsFileOpen(lfsPtr, fileNumber, &dirFilePtr);
  1275.     if (status != SUCCESS) {
  1276.         panic("Can't open lost+found file.\n");
  1277.     }
  1278.     }
  1279.     LfsFileClose(rootFilePtr);
  1280.     return dirFilePtr;
  1281. }
  1282.  
  1283.  
  1284.  
  1285.  
  1286. /*
  1287.  *----------------------------------------------------------------------
  1288.  *
  1289.  * RecoveryFile --
  1290.  *
  1291.  *    Roll forward changes to the descriptor map.
  1292.  *
  1293.  * Results:
  1294.  *    None.
  1295.  *
  1296.  * Side effects:
  1297.  *    None.
  1298.  *
  1299.  *----------------------------------------------------------------------
  1300.  */
  1301. void
  1302. RecoveryFile(fileNumber, address, descPtr)
  1303.     int        fileNumber;     /* File number to modified address of. */
  1304.     int        address;    /* Disk address of descriptor. */
  1305.     LfsFileDescriptor *descPtr; /* New file descriptor at address. */
  1306. {
  1307.     LfsDescMapEntry    *descMapEntryPtr;
  1308.     Boolean deallocate, wasAllocated;
  1309.     LfsFile        *oldFilePtr;
  1310.     LfsFile        *newFilePtr;
  1311.     ReturnStatus    status;
  1312.  
  1313.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  1314.     if (descMapEntryPtr == (LfsDescMapEntry *) NIL) {
  1315.     panic("Bad file number %d in call to RecoveryFile\n", fileNumber);
  1316.     return;
  1317.     }
  1318.     oldFilePtr = newFilePtr = (LfsFile *) NIL;
  1319.     deallocate = (address == FSDM_NIL_INDEX);
  1320.     wasAllocated = (descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED);
  1321.  
  1322.     if (wasAllocated) {
  1323.     status = LfsFileOpen(lfsPtr, fileNumber, &oldFilePtr);
  1324.     if (status != SUCCESS) {
  1325.         panic("RecoveryFile: Can't fetch old descriptor.\n");
  1326.     }
  1327.     LfsSegUsageAdjustBytes(lfsPtr,descMapEntryPtr->blockAddress,
  1328.                 -sizeof(LfsFileDescriptor));
  1329.     }
  1330.     if (verboseFlag) {
  1331.     if (wasAllocated) {
  1332.         printf("RecoveryFile %d was at %d ", fileNumber,    
  1333.                 descMapEntryPtr->blockAddress);
  1334.     } else {
  1335.         printf("RecoveryFile %d was not allocated ", fileNumber);
  1336.     }
  1337.     if (deallocate) {
  1338.         printf("is now deleted at %d\n", address);
  1339.     } else {
  1340.         printf("is now at %d\n", address);
  1341.     }
  1342.     }
  1343.  
  1344.  
  1345.  
  1346.     if (deallocate) {
  1347.     if (wasAllocated) {
  1348.         descMapEntryPtr->flags ^= LFS_DESC_MAP_ALLOCED;
  1349.         lfsPtr->descMap.checkPoint.numAllocDesc--;
  1350.     }
  1351.     } else {
  1352.     status = LfsFileOpenDesc(lfsPtr, descPtr, &newFilePtr);
  1353.     if (status != SUCCESS) {
  1354.         panic("RecoveryFile: Can't fetch new file.\n");
  1355.     }
  1356.     if (!wasAllocated) {
  1357.         descMapEntryPtr->flags |= LFS_DESC_MAP_ALLOCED;
  1358.         lfsPtr->descMap.checkPoint.numAllocDesc++;
  1359.     } 
  1360.     LfsSegUsageAdjustBytes(lfsPtr,address, sizeof(LfsFileDescriptor));
  1361.     }
  1362.     descMapEntryPtr->blockAddress = address;
  1363.     LfsDescMapEntryModified(lfsPtr, fileNumber);
  1364.     RecordBlockUsageChange(fileNumber, oldFilePtr, newFilePtr);
  1365.  
  1366.     if (oldFilePtr != (LfsFile *) NIL) {
  1367.     LfsFileClose(oldFilePtr);
  1368.     }
  1369.     if ((newFilePtr != (LfsFile *) NIL) && (newFilePtr != oldFilePtr)) {
  1370.     LfsFileClose(newFilePtr);
  1371.     }
  1372. }
  1373.  
  1374.  
  1375. /*
  1376.  *----------------------------------------------------------------------
  1377.  *
  1378.  * DescExists --
  1379.  *
  1380.  *    Determine if a file descriptor exists for the specified file.
  1381.  *
  1382.  * Results:
  1383.  *    None.
  1384.  *
  1385.  * Side effects:
  1386.  *    None.
  1387.  *
  1388.  *----------------------------------------------------------------------
  1389.  */
  1390.  
  1391. Boolean
  1392. DescExists(fileNumber)
  1393.     int    fileNumber;    /* File number to check for descriptor for. */
  1394. {
  1395.     LfsDescMapEntry    *descMapEntryPtr;
  1396.  
  1397.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  1398.     if (descMapEntryPtr == (LfsDescMapEntry *) NIL) {
  1399.     /*
  1400.      * Didn't exist at checkpoint. Check is see if we found it
  1401.      * in recovery log.
  1402.      */
  1403.     return FALSE;
  1404.     }
  1405.  
  1406.     if (!(descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  1407.     return     FALSE;
  1408.     }
  1409.     return TRUE;
  1410. }
  1411.  
  1412.  
  1413. /*
  1414.  *----------------------------------------------------------------------
  1415.  *
  1416.  * DirBlockStatus --
  1417.  *
  1418.  *    Compute the status of the directory block refered to a log 
  1419.  *    entry.
  1420.  *
  1421.  * Results:
  1422.  *    FORWARD, BACKWARD, or UNKNOWN
  1423.  *
  1424.  * Side effects:
  1425.  *    None.
  1426.  *
  1427.  *----------------------------------------------------------------------
  1428.  */
  1429.  
  1430. enum LogStatus
  1431. DirBlockStatus(dirFileNumber, dirOffset, startAddr, addr)
  1432.     int    dirFileNumber;    /* Directory being modified. */
  1433.     int    dirOffset;    /* Offset into directory being modified. */
  1434.     int    startAddr;    /* Disk Address of log start entry. */
  1435.     int    addr;        /* Disk Address of log end entry. */
  1436. {
  1437.     int    blockAddr;
  1438.     ReturnStatus    status;
  1439.     LfsFile        *dirFilePtr;
  1440.     int            blocksize;
  1441.  
  1442.  
  1443.     status = LfsFileOpen(lfsPtr, dirFileNumber, &dirFilePtr);
  1444.     if (status != SUCCESS) {
  1445.     if (status == FS_FILE_NOT_FOUND) {
  1446.         return BACKWARD;
  1447.     }
  1448.     panic("Can't find directory %d\n", dirFileNumber);
  1449.     return UNKNOWN;
  1450.     }
  1451.     blockAddr = LfsFileBlockAddr(dirFilePtr, dirOffset/FS_BLOCK_SIZE, &blocksize);
  1452.     LfsFileClose(dirFilePtr);
  1453.     if (blockAddr == FSDM_NIL_INDEX) {
  1454.     /*
  1455.      * Block doesn't exist, must be backward.
  1456.      */
  1457.     return BACKWARD;
  1458.     }
  1459.  
  1460.  
  1461.     if (AddrOlderThan(blockAddr, addr)) {
  1462.     return FORWARD;
  1463.     } 
  1464.     if (startAddr == addr) {
  1465.     return BACKWARD;
  1466.     } 
  1467.  
  1468.     if (AddrOlderThan(blockAddr, startAddr)) {
  1469.     return UNKNOWN;
  1470.     } else {
  1471.     return BACKWARD;
  1472.     }
  1473.  
  1474. }
  1475.  
  1476.  
  1477. /*
  1478.  *----------------------------------------------------------------------
  1479.  *
  1480.  * DescStatus --
  1481.  *
  1482.  *    Compute the status of the descriptor refered to a log 
  1483.  *    entry.
  1484.  *
  1485.  * Results:
  1486.  *    FORWARD, BACKWARD, or UNKNOWN
  1487.  *
  1488.  * Side effects:
  1489.  *    None.
  1490.  *
  1491.  *----------------------------------------------------------------------
  1492.  */
  1493.  
  1494. enum LogStatus
  1495. DescStatus(fileNumber, startAddr, addr)
  1496.     int    fileNumber;    /* Descriptor being looked for. */
  1497.     int    startAddr;    /* Disk Address of log start entry. */
  1498.     int    addr;        
  1499. {
  1500.     int    blockAddr;
  1501.     LfsDescMapEntry    *descMapEntryPtr;
  1502.     Boolean found;
  1503.  
  1504.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  1505.     if (descMapEntryPtr == (LfsDescMapEntry *) NIL) {
  1506.     panic("Bad file number %d in log entry\n", fileNumber);
  1507.     return BACKWARD;
  1508.     }
  1509.     if (!(descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  1510.     LfsFileDescriptor    *descPtr;
  1511.     found = FindNewDesc(fileNumber, &blockAddr, &descPtr);
  1512.     if (found) {
  1513.         /*
  1514.          * This was a file that was deleted during the trace,
  1515.          * mark it as forward.
  1516.          */
  1517.         return FORWARD;
  1518.     }  
  1519.     return BACKWARD;
  1520.     } else { 
  1521.     blockAddr = descMapEntryPtr->blockAddress;
  1522.     }
  1523.  
  1524.     if (AddrOlderThan(blockAddr, addr)) {
  1525.     return FORWARD;
  1526.     } 
  1527.     if (startAddr == addr) {
  1528.     return BACKWARD;
  1529.     } 
  1530.     if (AddrOlderThan(blockAddr, startAddr)) {
  1531.     return UNKNOWN;
  1532.     } else {
  1533.     return BACKWARD;
  1534.     }
  1535.  
  1536. }
  1537.  
  1538.  
  1539.  
  1540. /*
  1541.  *----------------------------------------------------------------------
  1542.  *
  1543.  * RecovFileLayoutSummary --
  1544.  *
  1545.  *    Check the segment summary regions for the file layout code.
  1546.  *
  1547.  * Results:
  1548.  *    None.
  1549.  *
  1550.  * Side effects:
  1551.  *    None.
  1552.  *
  1553.  *----------------------------------------------------------------------
  1554.  */
  1555. void
  1556. RecovFileLayoutSummary(lfsPtr, pass, segPtr, startAddr, offset, 
  1557.             segSummaryHdrPtr) 
  1558.     Lfs    *lfsPtr;    /* File system description. */
  1559.     enum Pass pass;    /* Pass number of recovery. */
  1560.     LfsSeg *segPtr;    /* Segment being examined. */
  1561.     int startAddr;   /* Starting address being examined. */
  1562.     int offset;        /* Offset into segment being examined. */
  1563.     LfsSegSummaryHdr *segSummaryHdrPtr; /* Summary header pointer */
  1564. {
  1565.     char *summaryPtr, *limitPtr;
  1566.     int descBlocks;
  1567.     int startAddress;
  1568.  
  1569.  
  1570.     startAddress = startAddr;
  1571.     descBlocks = (lfsPtr->superBlock.fileLayout.descPerBlock * 
  1572.             sizeof(LfsFileDescriptor))/blockSize;
  1573.     summaryPtr = (char *) (segSummaryHdrPtr + 1);
  1574.     limitPtr = summaryPtr + segSummaryHdrPtr->lengthInBytes - 
  1575.             sizeof(LfsSegSummaryHdr);
  1576.     /*
  1577.      * Scan thru summary region.
  1578.      */
  1579.     while (summaryPtr < limitPtr) {
  1580.     switch (*(unsigned short *) summaryPtr) {
  1581.     case LFS_FILE_LAYOUT_DESC: {
  1582.         int        fileNumber, slot, descPerBlock;
  1583.         LfsFileDescriptor    *descPtr;
  1584.  
  1585.         startAddress -= descBlocks;
  1586.         stats.descBlocks++;
  1587.         if (pass == PASS1) { 
  1588.         /*
  1589.          * During pass1 of recovery we simply record the location
  1590.          * of each the descriptors we find.
  1591.          */
  1592.         descPtr = (LfsFileDescriptor *) LfsSegFetchBlock(segPtr, offset, 
  1593.                         descBlocks*blockSize);
  1594.         descPerBlock = lfsPtr->superBlock.fileLayout.descPerBlock;
  1595.         for (slot = 0; slot < descPerBlock;  slot++) {
  1596.             /*
  1597.              * The descriptor block is terminated by an unallocated
  1598.              * descriptor.
  1599.              */
  1600.             if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  1601.             break;
  1602.             }
  1603.  
  1604.             fileNumber = descPtr[slot].fileNumber;
  1605.             if ((fileNumber < 0) || 
  1606.             (fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  1607.                fprintf(stderr,"%s:RecovFileLayoutSummary: bad file number %d in desc block at %d\n", deviceName, fileNumber, startAddress);
  1608.                continue;
  1609.             }
  1610.             stats.numDesc++;
  1611.             if (showLog) { 
  1612.             printf("Addr %d Descriptor %s %d len %d\n",
  1613.                 startAddress,
  1614.                 FileTypeToString(descPtr[slot].common.fileType),
  1615.                 descPtr[slot].fileNumber,
  1616.                 descPtr[slot].common.lastByte+1);
  1617.             }
  1618.             if (recreateDirEntries &&
  1619.                 (descPtr[slot].common.fileType == FS_DIRECTORY)) {
  1620.             continue;
  1621.             }
  1622.             /*
  1623.              * Record this descriptor location. 
  1624.              */
  1625.             RecordNewDesc(fileNumber, startAddress, descPtr+slot);
  1626.          }
  1627.          LfsSegReleaseBlock(segPtr, (char *) descPtr);
  1628.         }
  1629.         offset += descBlocks;
  1630.         /*
  1631.          * Skip over the summary bytes describing this block. 
  1632.          */
  1633.         summaryPtr += sizeof(LfsFileLayoutDesc);
  1634.         break;
  1635.     }
  1636.     case LFS_FILE_LAYOUT_DATA: {
  1637.         int    *blockArray;
  1638.         int              i;
  1639.         LfsFileLayoutSummary *fileSumPtr;
  1640.         int firstBlock;
  1641.         /*
  1642.          * Currently we don't do much with data blocks by themselves.
  1643.          * We can only hope that the descriptor also made it out and
  1644.          * points to them.
  1645.          */
  1646.         fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  1647.         if ((fileSumPtr->fileNumber < 0) || 
  1648.         (fileSumPtr->fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  1649.            fprintf(stderr,"%s:RecovFileLayoutSummary: bad file number %d at %d\n", deviceName, fileSumPtr->fileNumber, startAddress);
  1650.            goto out;
  1651.         }
  1652.         blockArray = (int *)(summaryPtr + sizeof(LfsFileLayoutSummary));
  1653.         if (pass == PASS1) { 
  1654.         if (showLog) { 
  1655.             printf("Addr %d File %d blocks %d version %d dataBlocks %d\n",
  1656.             startAddress - fileSumPtr->numBlocks,
  1657.             fileSumPtr->fileNumber, fileSumPtr->numBlocks,
  1658.             fileSumPtr->truncVersion,
  1659.             fileSumPtr->numDataBlocks);
  1660.             /*
  1661.              * For each block ... 
  1662.              */
  1663.             firstBlock = fileSumPtr->numBlocks -
  1664.              (fileSumPtr->numDataBlocks-1) *
  1665.                         FS_BLOCK_SIZE/blockSize;
  1666.             stats.numFileBlocks += fileSumPtr->numDataBlocks;
  1667.             for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  1668.             int addr;
  1669.     
  1670.             addr = startAddress - i*FS_BLOCK_SIZE/blockSize - 
  1671.                     firstBlock;
  1672.                 printf("Addr %d File %d block %d\n",
  1673.                 addr, fileSumPtr->fileNumber, blockArray[i]);
  1674.             }
  1675.         }
  1676.         } else {
  1677.         CheckVersionTruncNum(startAddress, fileSumPtr->fileNumber, 
  1678.                 fileSumPtr->truncVersion,
  1679.                  fileSumPtr->numBlocks,
  1680.                 fileSumPtr->numDataBlocks, blockArray);
  1681.  
  1682.         }
  1683.         out:
  1684.         startAddress = startAddress - fileSumPtr->numBlocks;
  1685.         offset += fileSumPtr->numBlocks;
  1686.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  1687.                 fileSumPtr->numDataBlocks * sizeof(int); 
  1688.         break;
  1689.       }
  1690.  
  1691.     case LFS_FILE_LAYOUT_DIR_LOG: {
  1692.         LfsFileLayoutLog    *logSumPtr;
  1693.         int            numBlocks;
  1694.         int            i, addr, blocks;
  1695.         LfsDirOpLogBlockHdr *hdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  1696.  
  1697.         /* 
  1698.          * Directory log info is needed during both passes.  
  1699.          */
  1700.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  1701.          summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  1702.          numBlocks = logSumPtr->numBlocks;
  1703.          addr = startAddress;
  1704.          for (i = 0; i < logSumPtr->numDataBlocks; i++) {
  1705.         if (numBlocks > FS_BLOCK_SIZE/blockSize) {
  1706.             blocks = FS_BLOCK_SIZE/blockSize;
  1707.         } else {
  1708.             blocks = numBlocks;
  1709.         }
  1710.  
  1711.             hdrPtr = (LfsDirOpLogBlockHdr *)
  1712.              LfsSegFetchBlock(segPtr, offset, blocks*blockSize);
  1713.         addr -= blocks;
  1714.         offset += blocks;
  1715.         numBlocks -= blocks;
  1716.         if (hdrPtr->magic != LFS_DIROP_LOG_MAGIC) {
  1717.             fprintf(stderr,"Bad dir op log magic number.\n");
  1718.         }
  1719.         if (pass == PASS1) { 
  1720.             stats.numDirLogBlocks += blocks;
  1721.             if (showLog) { 
  1722.             ShowDirLogBlock(hdrPtr, addr);
  1723.             }
  1724.         }
  1725.  
  1726.         RecovDirLogBlock(hdrPtr, addr, pass);
  1727.         /*
  1728.          * Could save log in memory for second pass.
  1729.          */
  1730.         LfsSegReleaseBlock(segPtr, (char *) hdrPtr);
  1731.         }
  1732.  
  1733.         startAddress = startAddress - logSumPtr->numBlocks;
  1734.         break;
  1735.     }
  1736.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  1737.     case LFS_FILE_LAYOUT_INDIRECT: 
  1738.     default: {
  1739.         panic("Unknown type");
  1740.     }
  1741.       }
  1742.     }
  1743. }
  1744.  
  1745.  
  1746. /*
  1747.  *----------------------------------------------------------------------
  1748.  *
  1749.  * CheckVersionTruncNum --
  1750.  *
  1751.  *    Record the a truncate version number at a specified address.
  1752.  *
  1753.  * Results:
  1754.  *    None.
  1755.  *
  1756.  * Side effects:
  1757.  *
  1758.  *----------------------------------------------------------------------
  1759.  */
  1760.  
  1761. void
  1762. CheckVersionTruncNum(startAddress, fileNumber, truncVersion, numBlocks,
  1763.             numDataBlocks, blockArray)
  1764.     int     startAddress;
  1765.     int    fileNumber;    /* File number of descriptor. */
  1766.     int    truncVersion;    /* Truncate version number. */
  1767.     int    numBlocks;    /* Fs block. */
  1768.     int numDataBlocks;    /* Number of blocks in list.*/
  1769.     int    *blockArray;    /* List of blocks. */
  1770. {
  1771.  
  1772.     LfsDescMapEntry    *descMapEntryPtr;
  1773.     int        addr;
  1774.     int        firstBlock;
  1775.     LfsFile    *filePtr;
  1776.     int        size, i;
  1777.     ReturnStatus status;
  1778.  
  1779.     descMapEntryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  1780.     if (descMapEntryPtr == (LfsDescMapEntry *) NIL) {
  1781.     panic("Bad file number %d in call to RecordVersionTrunc\n", fileNumber);
  1782.     return;
  1783.     }
  1784.     if (!(descMapEntryPtr->flags & LFS_DESC_MAP_ALLOCED)) {
  1785.     return;
  1786.     }
  1787.     if (descMapEntryPtr->truncVersion >= truncVersion) {
  1788.     return;
  1789.     }
  1790.     if (AddrOlderThan(startAddress, descMapEntryPtr->blockAddress)) {
  1791.     /*
  1792.      * Blocks are before the descriptor in the log.  Assume that
  1793.      * the descriptor includes these blocks. 
  1794.      */
  1795.     descMapEntryPtr->truncVersion = truncVersion;
  1796.     LfsDescMapEntryModified(lfsPtr, fileNumber);
  1797.     return;
  1798.     }
  1799.     /*
  1800.      * Could be newer than. 
  1801.      */
  1802.      if (LfsDiskAddrToSegmentNum(lfsPtr, startAddress) !=
  1803.      LfsDiskAddrToSegmentNum(lfsPtr, descMapEntryPtr->blockAddress)) {
  1804.     /*
  1805.      * If it is new and in a different segment it can't be part
  1806.      * of this file.
  1807.      */
  1808.      return;
  1809.     }
  1810.     /*
  1811.      * Same segment. Check the blocks to see if any are in file.
  1812.      */
  1813.     status = LfsFileOpen(lfsPtr, fileNumber, &filePtr);
  1814.     if (status != SUCCESS) {
  1815.     return;
  1816.     }
  1817.     firstBlock = numBlocks - ( numDataBlocks-1 ) *
  1818.                 FS_BLOCK_SIZE/blockSize;
  1819.     for (i = 0; i < numDataBlocks; i++) {
  1820.  
  1821.     addr = startAddress - i*FS_BLOCK_SIZE/blockSize - 
  1822.             firstBlock;
  1823.     if (LfsFileBlockAddr(filePtr, blockArray[i], &size) == addr) {
  1824.         descMapEntryPtr->truncVersion = truncVersion;
  1825.         LfsDescMapEntryModified(lfsPtr, fileNumber);
  1826.         LfsFileClose(filePtr);
  1827.         return;
  1828.     }
  1829.     }
  1830.     LfsFileClose(filePtr);
  1831. }
  1832.  
  1833.